package com.farm.kaiping.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.farm.common.config.JwtConfig;
import com.farm.common.constant.CommonConstants;
import com.farm.common.security.SecurityUtils;
import com.farm.common.util.JwtTokenUtil;
import com.farm.kaiping.entity.*;
import com.farm.kaiping.po.SysDeptPO;
import com.farm.kaiping.po.SysRolePO;
import com.farm.kaiping.po.SysUserLoginPO;
import com.farm.kaiping.po.SysUserPO;
import com.farm.kaiping.mapper.SysUserMapper;
import com.farm.kaiping.service.SysDeptService;
import com.farm.kaiping.service.SysRoleService;
import com.farm.kaiping.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.farm.common.util.StringRange;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户表(SysUser)表服务实现类
 *
 * @author farm
 * @since 2024
 */
@Service
@Slf4j
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
	private RedisTemplate redisTemplate;
	private StringRedisTemplate stringRedisTemplate;
	@Autowired
	private JwtTokenUtil jwtTokenUtil;
	@Autowired
	private JwtConfig jwtConfig;
    private final SysRoleService sysRoleService;
	private final SysDeptService sysDeptService;
	private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();
    
	private LambdaQueryWrapper<SysUser> generateQueryWrapper(SysUserPO sysUserPO){
		LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
		// 主键ID(用户ID)
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getUserId()), SysUser::getUserId, sysUserPO.getUserId());
		queryWrapper.in(ObjectUtil.isNotEmpty(sysUserPO.getUserIdList()), SysUser::getUserId, sysUserPO.getUserIdList());
		// 用户名
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getUsername()), SysUser::getUsername, sysUserPO.getUsername());
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getSalt()), SysUser::getSalt, sysUserPO.getSalt());
		// 电话，手机号
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getPhone()), SysUser::getPhone, sysUserPO.getPhone());
		// 头像地址
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getAvatar()), SysUser::getAvatar, sysUserPO.getAvatar());
		// 身份证
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getIdCard()), SysUser::getIdCard, sysUserPO.getIdCard());
		// 性别
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getSex()), SysUser::getSex, sysUserPO.getSex());
		// 出生日期
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getBirthDay()), SysUser::getBirthDay, sysUserPO.getBirthDay());
		// 角色ID
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getRoleId()), SysUser::getRoleId, sysUserPO.getRoleId());
		// 部门ID
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getDeptId()), SysUser::getDeptId, sysUserPO.getDeptId());
		// 账户状态 1开启 2关闭
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getLockFlag()), SysUser::getLockFlag, sysUserPO.getLockFlag());
		// 微信登录openId
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getWxOpenid()), SysUser::getWxOpenid, sysUserPO.getWxOpenid());
		// 小程序openId
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getMiniOpenid()), SysUser::getMiniOpenid, sysUserPO.getMiniOpenid());
		// 创建时间
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getCreateTime()), SysUser::getCreateTime, sysUserPO.getCreateTime());
		// 编辑时间
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getUpdateTime()), SysUser::getUpdateTime, sysUserPO.getUpdateTime());
		// 删除时间
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getDelFlag()), SysUser::getDelFlag, sysUserPO.getDelFlag());
        queryWrapper.eq(ObjectUtil.isEmpty(sysUserPO.getDelFlag()), SysUser::getDelFlag, 0);
		// 创建人
		queryWrapper.eq(ObjectUtil.isNotEmpty(sysUserPO.getCreateUserId()), SysUser::getCreateUserId, sysUserPO.getCreateUserId());
		// 真实姓名
		queryWrapper.like(ObjectUtil.isNotEmpty(sysUserPO.getRealName()), SysUser::getRealName, sysUserPO.getRealName());

		// 创建时间时间区间查询
		queryWrapper.ge(ObjectUtil.isNotEmpty(StringRange.getOne(sysUserPO.getCreateTimeBetween(),0)), SysUser::getCreateTime,StringRange.getOne(sysUserPO.getCreateTimeBetween(),0));
		queryWrapper.le(ObjectUtil.isNotEmpty(StringRange.getOne(sysUserPO.getCreateTimeBetween(),1)), SysUser::getCreateTime,StringRange.getOne(sysUserPO.getCreateTimeBetween(),1));
		// 更新时间时间区间查询
		queryWrapper.ge(ObjectUtil.isNotEmpty(StringRange.getOne(sysUserPO.getUpdateTimeBetween(),0)), SysUser::getUpdateTime,StringRange.getOne(sysUserPO.getUpdateTimeBetween(),0));
		queryWrapper.le(ObjectUtil.isNotEmpty(StringRange.getOne(sysUserPO.getUpdateTimeBetween(),1)), SysUser::getUpdateTime,StringRange.getOne(sysUserPO.getUpdateTimeBetween(),1));

		queryWrapper.orderByDesc(SysUser::getCreateTime,SysUser::getUserId);
		return queryWrapper;
	}

	/**
	  * @describe 分页查询用户表
	  * @author farm
      * @since 2024
	  */
	@Override
	public Page<SysUser> getSysUserPage(Page page, SysUserPO sysUserPO){
		LambdaQueryWrapper<SysUser> queryWrapper = this.generateQueryWrapper(sysUserPO);
		Page<SysUser> page1 = this.baseMapper.selectPage(page, queryWrapper);
		List<SysUser> records = page1.getRecords();
		List<Integer> roleIds = records.stream().map(SysUser::getRoleId).filter(ObjectUtil::isNotEmpty).distinct().collect(Collectors.toList());
		List<Integer> deptIds = records.stream().map(SysUser::getDeptId).filter(ObjectUtil::isNotEmpty).distinct().collect(Collectors.toList());

		Map<Integer, SysRole> sysRoleMap = new HashMap<>();
		if (ObjectUtil.isNotEmpty(roleIds)){
			SysRolePO sysRolePO = new SysRolePO();
			sysRolePO.setRoleIdList(roleIds);
			List<SysRole> sysRoleList = sysRoleService.getSysRoleList(sysRolePO);
			sysRoleMap = sysRoleList.stream().collect(Collectors.toMap(SysRole::getRoleId, sysRole -> sysRole));
		}
		Map<Integer, SysDept> sysDeptMap = new HashMap<>();
		if (ObjectUtil.isNotEmpty(deptIds)){
			SysDeptPO sysDeptPO = new SysDeptPO();
			sysDeptPO.setDeptIdList(deptIds);
			List<SysDept> sysDeptList = sysDeptService.getSysDeptList(sysDeptPO);
			sysDeptMap = sysDeptList.stream().collect(Collectors.toMap(SysDept::getDeptId, sysDept -> sysDept));
		}

		for (SysUser record : page1.getRecords()) {
			if (ObjectUtil.isNotEmpty(record.getRoleId()) && ObjectUtil.isNotEmpty(sysRoleMap.get(record.getRoleId()))){
				record.setSysRole(sysRoleMap.get(record.getRoleId()));
				record.setRoleCode(sysRoleMap.get(record.getRoleId()).getRoleCode());
			}
			if (ObjectUtil.isNotEmpty(record.getDeptId()) && ObjectUtil.isNotEmpty(sysDeptMap)){
				record.setSysDept(sysDeptMap.get(record.getDeptId()));
			}
		}
		page1.setRecords(records);
		return page1;
	}
	
	/**
     * @describe 查询用户表list
     * @author farm
	 * @since 2024
     */
	@Override
	public List<SysUser> getSysUserList(SysUserPO sysUserPO){
		LambdaQueryWrapper<SysUser> queryWrapper = this.generateQueryWrapper(sysUserPO);
		List<SysUser> sysUsers = this.baseMapper.selectList(queryWrapper);

		List<Integer> roleIds = sysUsers.stream().map(SysUser::getRoleId).filter(ObjectUtil::isNotEmpty).distinct().collect(Collectors.toList());
		List<Integer> deptIds = sysUsers.stream().map(SysUser::getDeptId).filter(ObjectUtil::isNotEmpty).distinct().collect(Collectors.toList());

		Map<Integer, SysRole> sysRoleMap = new HashMap<>();
		if (ObjectUtil.isNotEmpty(roleIds)){
			SysRolePO sysRolePO = new SysRolePO();
			sysRolePO.setRoleIdList(roleIds);
			List<SysRole> sysRoleList = sysRoleService.getSysRoleList(sysRolePO);
			sysRoleMap = sysRoleList.stream().collect(Collectors.toMap(SysRole::getRoleId, sysRole -> sysRole));
		}
		Map<Integer, SysDept> sysDeptMap = new HashMap<>();
		if (ObjectUtil.isNotEmpty(deptIds)){
			SysDeptPO sysDeptPO = new SysDeptPO();
			sysDeptPO.setDeptIdList(deptIds);
			List<SysDept> sysDeptList = sysDeptService.getSysDeptList(sysDeptPO);
			sysDeptMap = sysDeptList.stream().collect(Collectors.toMap(SysDept::getDeptId, sysDept -> sysDept));
		}

		for (SysUser record : sysUsers) {
			if (ObjectUtil.isNotEmpty(record.getRoleId()) && ObjectUtil.isNotEmpty(sysRoleMap.get(record.getRoleId()))){
				record.setSysRole(sysRoleMap.get(record.getRoleId()));
				record.setRoleCode(sysRoleMap.get(record.getRoleId()).getRoleCode());
			}
			if (ObjectUtil.isNotEmpty(record.getDeptId()) && ObjectUtil.isNotEmpty(sysDeptMap)){
				record.setSysDept(sysDeptMap.get(record.getDeptId()));
			}
		}
		return sysUsers;
	}
	
	/**
     * @describe 获取一条数据 用户表
     * @author farm
	 * @since 2024
     */
	@Override
	public SysUser getSysUser(SysUserPO sysUserPO){
		LambdaQueryWrapper<SysUser> queryWrapper = this.generateQueryWrapper(sysUserPO);
        queryWrapper.last("LIMIT 1");
        return this.baseMapper.selectOne(queryWrapper);
	}

	@Override
	public SysUser getSysUser(String userName) {
		if (ObjectUtil.isEmpty(userName)){
			return null;
		}
		LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(SysUser::getDelFlag,0);
		queryWrapper.and(w->{
			w.eq(SysUser::getUsername,userName)
				.or().eq(SysUser::getPhone,userName)
				.or().eq(SysUser::getIdCard,userName);
		});
		queryWrapper.last("LIMIT 1");
		return this.baseMapper.selectOne(queryWrapper);
	}

	@Override
	public SysUser getSysUser(Integer userId) {
		if (ObjectUtil.isEmpty(userId)){
			return null;
		}
		LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(SysUser::getDelFlag,0);
		queryWrapper.eq(SysUser::getUserId,userId);
		queryWrapper.last("LIMIT 1");
		return this.baseMapper.selectOne(queryWrapper);
	}

	@Override
	public SysUser getSysUserByUserPhone(String phone) {
		if (ObjectUtil.isEmpty(phone)){
			return null;
		}
		SysUserPO sysUserPO = new SysUserPO();
		sysUserPO.setPhone(phone);
		return this.getSysUser(sysUserPO);
	}

	@Override
	public SysUser getSysUserByIdCard(String idCard) {
		if (ObjectUtil.isEmpty(idCard)){
			return null;
		}
		SysUserPO sysUserPO = new SysUserPO();
		sysUserPO.setIdCard(idCard);
		return this.getSysUser(sysUserPO);
	}

	@Override
	public Integer saveSysUser(SysUserPO sysUserPO) {
		if (ObjectUtil.isEmpty(sysUserPO.getUsername())){
			throw new RuntimeException("用户名不能为空");
		}
		if (ObjectUtil.isEmpty(sysUserPO.getPassword())){
			throw new RuntimeException("密码不能为空");
		}
		sysUserPO.setOldPassword(sysUserPO.getPassword());
		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
		Set<ConstraintViolation<SysUserPO>> violations = validator.validate(sysUserPO);
		for (ConstraintViolation<SysUserPO> violation : violations) {
			throw new RuntimeException(violation.getMessage());
		}
		sysUserPO.setPassword(ENCODER.encode(sysUserPO.getPassword()));

		if (ObjectUtil.isEmpty(sysUserPO.getRoleId())){
			throw new RuntimeException("角色不能为空");
		}
		if (ObjectUtil.isEmpty(sysUserPO.getClassifyId())){
			throw new RuntimeException("用户类型不能为空");
		}
		if (ObjectUtil.isEmpty(sysUserPO.getRealName())){
			throw new RuntimeException("真实姓名不能为空");
		}
		if (ObjectUtil.isNotEmpty(sysUserPO.getIdCard())){
			if (!IdcardUtil.isValidCard(sysUserPO.getIdCard())){
				throw new RuntimeException("身份证格式错误");
			}
			DateTime birthDate = IdcardUtil.getBirthDate(sysUserPO.getIdCard());
			LocalDate parse = LocalDate.parse(birthDate.toDateStr());
			sysUserPO.setBirthDay(parse);
			int genderByIdCard = IdcardUtil.getGenderByIdCard(sysUserPO.getIdCard());
			sysUserPO.setSex(genderByIdCard == 1?1:2);
		}

		if (ObjectUtil.isNotEmpty(sysUserPO.getPhone())){
			if (!PhoneUtil.isPhone(sysUserPO.getPhone())){
				throw new RuntimeException("手机号格式错误");
			}
		}

		LambdaQueryWrapper<SysUser> existQueryWrapper = new LambdaQueryWrapper<>();
		existQueryWrapper.eq(SysUser::getUsername, sysUserPO.getUsername());
		existQueryWrapper.eq(SysUser::getDelFlag, 0);
		if (this.baseMapper.selectCount(existQueryWrapper) > 0){
			throw new RuntimeException("用户名已存在");
		}

		sysUserPO.setDelFlag(0);
		sysUserPO.setTenantId(SecurityUtils.getUser().getTenantId());// 租户ID
		sysUserPO.setCreateTime(LocalDateTime.now());
		sysUserPO.setCreateUserId(SecurityUtils.getUser().getUserId());// 创建人
		sysUserPO.setCreateUserName(SecurityUtils.getUser().getRealName());// 创建人
		sysUserPO.setUpdateTime(LocalDateTime.now());
		SysUser sysUser = BeanUtil.copyProperties(sysUserPO, SysUser.class);
		this.save(sysUser);
		return sysUser.getUserId();
	}

	/**
     * @describe 修改用户表
     * @author farm
	 * @since 2024
     */
	@Override
	public String updateSysUser(SysUserPO sysUserPO) {
		if (ObjectUtil.isEmpty(sysUserPO.getUserId())) {
			throw new RuntimeException("id为空");
		}

		if (ObjectUtil.isNotEmpty(sysUserPO.getPassword())){
			if (sysUserPO.getPassword().length() < 6 || sysUserPO.getPassword().length() > 255){
				throw new RuntimeException("密码长度在6~255个字符之间");
			}
			sysUserPO.setPassword(ENCODER.encode(sysUserPO.getPassword()));
		}

		if (ObjectUtil.isNotEmpty(sysUserPO.getIdCard())){
			if (!IdcardUtil.isValidCard(sysUserPO.getIdCard())){
				throw new RuntimeException("身份证格式错误");
			}
			DateTime birthDate = IdcardUtil.getBirthDate(sysUserPO.getIdCard());
			LocalDate parse = LocalDate.parse(birthDate.toDateStr());
			sysUserPO.setBirthDay(parse);
			int genderByIdCard = IdcardUtil.getGenderByIdCard(sysUserPO.getIdCard());
			sysUserPO.setSex(genderByIdCard == 1?1:2);
		}

		if (ObjectUtil.isNotEmpty(sysUserPO.getPhone())){
			if (!PhoneUtil.isPhone(sysUserPO.getPhone())){
				throw new RuntimeException("手机号格式错误");
			}
		}

		LambdaQueryWrapper<SysUser> existQueryWrapper = new LambdaQueryWrapper<>();
		existQueryWrapper.ne(SysUser::getUserId, sysUserPO.getUserId());
		existQueryWrapper.eq(SysUser::getUsername, sysUserPO.getUsername());
		existQueryWrapper.eq(SysUser::getDelFlag, 0);
		if (this.baseMapper.selectCount(existQueryWrapper) > 0){
			throw new RuntimeException("用户名已存在");
		}

		sysUserPO.setUpdateUserId(SecurityUtils.getUser().getUserId());// 更新人
		sysUserPO.setUpdateUserName(SecurityUtils.getUser().getRealName());// 更新人
		sysUserPO.setUpdateTime(LocalDateTime.now());
		SysUser sysUser = BeanUtil.copyProperties(sysUserPO, SysUser.class);
		this.updateById(sysUser);
		return "修改成功";
	}

	/**
     * @describe 通过id删除用户表
     * @author farm
	 * @since 2024
     */
	@Override
	public String removeSysUser(SysUserPO sysUserPO) {
		if (ObjectUtil.isEmpty(sysUserPO.getBatchDel())) {
			throw new RuntimeException("删除数据未选择");
		}
		LambdaUpdateWrapper<SysUser> removeWrapper = new LambdaUpdateWrapper<>();
		removeWrapper.in(SysUser::getUserId, sysUserPO.getBatchDel());
		removeWrapper.set(SysUser::getDelFlag,1);
		this.update(removeWrapper);
		return "删除成功";
	}

	@Override
	public FarmUser getUserLogin(SysUserLoginPO sysUserLoginPO) {
		System.out.println("用户登录");
		// 校验登录参数
		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
		Set<ConstraintViolation<SysUserLoginPO>> violations = validator.validate(sysUserLoginPO);
		for (ConstraintViolation<SysUserLoginPO> violation : violations) {
			throw new RuntimeException(violation.getMessage());
		}
		// 获取用户
		SysUser sysUser = this.getSysUser(sysUserLoginPO.getUsername());
		if (ObjectUtil.isEmpty(sysUser)){
			throw new RuntimeException("用户不存在");
		}
		// 验证用户是否锁定
		if (ObjectUtil.isNotEmpty(sysUser.getLockTime()) && sysUser.getLockTime().isBefore(LocalDateTime.now())){
			sysUser.setLockFlag(0);
			stringRedisTemplate.opsForValue().set(StrUtil.format(CommonConstants.USER_LOCK, sysUser.getUserId()), "0", 1, TimeUnit.SECONDS);
		}
		if (ObjectUtil.isNotEmpty(sysUser.getLockFlag()) && sysUser.getLockFlag().equals(1)){
			throw new RuntimeException("用户已锁定");
		}
		LambdaUpdateWrapper<SysUser> updateWrapper = new LambdaUpdateWrapper<>();
		updateWrapper.eq(SysUser::getUserId, sysUser.getUserId());
		if (!ENCODER.matches(sysUserLoginPO.getPassword(), sysUser.getPassword())){
			String lockTimes = stringRedisTemplate.opsForValue().get(StrUtil.format(CommonConstants.USER_LOCK, sysUser.getUserId()));
			if (ObjectUtil.isEmpty(lockTimes) || ObjectUtil.isNull(lockTimes)){
				stringRedisTemplate.opsForValue().set(StrUtil.format(CommonConstants.USER_LOCK, sysUser.getUserId()), "1");
			}else{
				int times = Integer.parseInt(lockTimes) + 1;
				stringRedisTemplate.opsForValue().set(StrUtil.format(CommonConstants.USER_LOCK, sysUser.getUserId()),String.valueOf(times));
				// 密码错误5次 账号锁定
				if (times >= 5){
					updateWrapper.set(SysUser::getLockFlag, 1);
					updateWrapper.set(SysUser::getLockTime, LocalDateTime.now().plusMinutes(5));
					this.update(updateWrapper);
				}
			}
			throw new RuntimeException("密码错误");
		}else{
			// 密码错误5次 账号锁定 解除锁定
			updateWrapper.set(SysUser::getLockFlag, 0);
			SysUser sysUser1 = new SysUser();
			sysUser1.setLockTime(null);
			stringRedisTemplate.opsForValue().set(StrUtil.format(CommonConstants.USER_LOCK, sysUser.getUserId()), "0", 1, TimeUnit.SECONDS);
			this.update(sysUser1,updateWrapper);
			updateWrapper.clear();
		}

		// 记录最后一次登录时间
		updateWrapper.eq(SysUser::getUserId, sysUser.getUserId());
		updateWrapper.set(SysUser::getLoginTime, LocalDateTime.now());
		this.update(updateWrapper);

		// 获取角色信息和角色菜单列表
		if (ObjectUtil.isNotEmpty(sysUser.getRoleId())){
			SysRolePO sysRolePO = new SysRolePO();
			sysRolePO.setRoleId(sysUser.getRoleId());
			SysRole sysRole = sysRoleService.getSysRole(sysRolePO);
			sysUser.setSysRole(sysRole);
			sysUser.setRoleCode(ObjectUtil.isNotEmpty(sysRole)?sysRole.getRoleCode():null);

			List<SysMenu> sysRoleMenu = sysRoleService.getSysRoleMenu(sysUser.getRoleId());
			// sysUser.setMenuList(sysRoleMenu);
			if (ObjectUtil.isNotEmpty(sysRoleMenu)){
				List<String> permissions = sysRoleMenu.stream().map(SysMenu::getPermission).filter(ObjectUtil::isNotEmpty).distinct().collect(Collectors.toList());
				sysUser.setPermissions(permissions);
			}
		}
		// 获取部门信息
		if (ObjectUtil.isNotEmpty(sysUser.getDeptId())){
			SysDeptPO sysDeptPO = new SysDeptPO();
			sysDeptPO.setDeptId(sysUser.getDeptId());
			SysDept sysDept = sysDeptService.getSysDept(sysDeptPO);
			sysUser.setSysDept(sysDept);
		}
		sysUser.setPassword(null);
		String jsonStr = JSON.toJSONStringWithDateFormat(sysUser, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat);
		redisTemplate.opsForValue().set(StrUtil.format(CommonConstants.USER_INFO,sysUser.getUserId()), jsonStr, jwtConfig.getTokenRefreshExpireTime(), TimeUnit.SECONDS);

		FarmUser farmUser = convertUserDetails(sysUser);
		// 生成token
		String token = jwtTokenUtil.generateToken(sysUser.getUserId());
		farmUser.setToken(token);
		farmUser.setTokenExpireTime(jwtConfig.getTokenExpireTime());
		return farmUser;
	}

	private FarmUser convertUserDetails(SysUser user) {
		FarmUser farmUser = new FarmUser();
		farmUser.setUserId(user.getUserId());
		farmUser.setUsername(user.getUsername());
		farmUser.setRealName(user.getRealName());
		farmUser.setPhone(user.getPhone());
		farmUser.setAvatar(user.getAvatar());
		farmUser.setIdCard(user.getIdCard());
		farmUser.setSex(user.getSex());
		farmUser.setBirthDay(user.getBirthDay());

		farmUser.setDeptId(user.getDeptId());
		farmUser.setDeptName(ObjectUtil.isNotEmpty(user.getSysDept())?user.getSysDept().getName():null);
		farmUser.setRoleId(user.getRoleId());
		farmUser.setRoleName(ObjectUtil.isNotEmpty(user.getSysRole())?user.getSysRole().getRoleName():null);
		farmUser.setRoleCode(ObjectUtil.isNotEmpty(user.getSysRole())?user.getSysRole().getRoleCode():null);
		farmUser.setClassifyId(user.getClassifyId());
		farmUser.setTenantId(user.getTenantId());

		farmUser.setWxOpenid(user.getWxOpenid());
		// farmUser.setWxUnionId(user.getWxUnionId());
		farmUser.setMiniOpenid(user.getMiniOpenid());

		farmUser.setPasswordModifyTime(user.getPasswordModifyTime());
		farmUser.setLoginTime(user.getLoginTime());
		farmUser.setCreateTime(user.getCreateTime());
		farmUser.setUpdateTime(user.getUpdateTime());

		farmUser.setPermissions(user.getPermissions());

		return farmUser;
	}

	@Override
	public FarmUser getCacheSysUserByUserId(Integer userId) {
		if (ObjectUtil.isEmpty(userId)){
			throw new RuntimeException("用户ID为空");
		}

		Object o = redisTemplate.opsForValue().get(StrUtil.format(CommonConstants.USER_INFO, userId));
		if (o != null){
			SysUser sysUser = JSONObject.toJavaObject(JSONObject.parseObject(o.toString()), SysUser.class);
			return convertUserDetails(sysUser);
		}
		return null;
	}

	@Override
	public String changePassword(SysUserPO sysUserPO) {
		if (ObjectUtil.isEmpty(sysUserPO.getOldPassword())){
			throw new RuntimeException("旧密码为空");
		}
		sysUserPO.setPassword(ENCODER.encode(sysUserPO.getPassword()));
		if (ObjectUtil.isEmpty(sysUserPO.getPassword())){
			throw new RuntimeException("新密码为空");
		}
		if (sysUserPO.getPassword().length() < 6 || sysUserPO.getPassword().length() > 255){
			throw new RuntimeException("新密码长度在6~255个字符之间");
		}

		SysUser sysUser = this.getSysUser(SecurityUtils.getUser().getUserId());

		if (!ENCODER.matches(sysUserPO.getOldPassword(), sysUser.getPassword())) {
			throw new RuntimeException("旧密码错误");
		}

		sysUserPO.setPassword(ENCODER.encode(sysUserPO.getPassword()));

		LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
		sysUserLambdaUpdateWrapper.eq(SysUser::getUserId, sysUser.getUserId());
		sysUserLambdaUpdateWrapper.set(SysUser::getPassword, sysUserPO.getPassword());
		sysUserLambdaUpdateWrapper.set(SysUser::getPasswordModifyTime, LocalDateTime.now());
		this.update(sysUserLambdaUpdateWrapper);

		return "密码修改成功";
	}

}

